from django.db import models
from base import *
from object_types import *
from simdb import *
from protocol import *

_model_names = ["DataCollection", "Experiment",  "ParameterSetting",
                "Snapshot", "TargetObjectType",
                "TargetProcess", "ObjectCollection",
                "Characterisation", "File", "Array"]

__all__ = _model_names + ["CHARACTERISATION_TYPES"]

CHARACTERISATION_TYPES = (("nominal",
                           "A typical value, as judged by the publisher of the snapshots."),
                          ("min",
                           "Represents the minimum  ('possible' if a priori, 'attained' if a osteriori) value for the characterised property."),
                          ("max",
                           "Represents the maximum  ('possible' if a priori, 'attained' if a osteriori) value for the characterised property."),
                          ("mean",
                           "Represents the mean  ('expected' if a priori, 'attained' if a posteriori) value for the characterised property."),
                          ("stdev",
                           "Represents the expected/attained standard deviation for the characterised property."))

class DataCollection(Resource):
    _collection_sets = ['child_collections']
    parent_collection = models.ForeignKey('self', 
                                          related_name='child_collections', 
                                          blank=True, null=True)
    _container_field = 'parent_collection_id'

class Experiment(Resource):
    _collection_sets = []
    collection = models.ForeignKey(DataCollection)
    protocol = models.ForeignKey(Protocol, blank=True, null=True)
    executiontime = models.DateTimeField(blank=True, null=True)
    appliedphysics = models.ManyToManyField(Physics)
    inputdatasets = models.ManyToManyField('Snapshot', 
                                           related_name='experiment_inputdatasets')
    _container_field = 'collection_id'
    DataCollection._collection_sets.append('experiment_set')

class ParameterSetting(MetadataObject):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    parameter = models.ForeignKey(InputParameter, blank=True, null=True)
    parameter_name = models.CharField(max_length=256, blank=True, null=True)
    value = models.TextField(blank=True, null=True)
    units = models.TextField(blank=True, null=True)
    Experiment._collection_sets.append('parametersetting_set')
    _container_field = "experiment_id"

    def __unicode__(self):
        return u'%s: %s = %s' % (self.experiment.name, self.parameter_name, self.value)

class Snapshot(MetadataObject):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    publisherDID = models.SlugField(blank=True)
    time_value = models.CharField(max_length=1024, blank=True)
    time_unit = models.CharField(max_length=1024, blank=True)
    spatialsizephysical_value = models.CharField(max_length=1024, blank=True)
    spatialsizephysical_unit = models.CharField(max_length=1024, blank=True)
    _container_field = "experiment_id"
    Experiment._collection_sets.append('snapshot_set')

class File(MetadataObject):
    _collection_sets = []
    snapshot = models.ForeignKey(Snapshot)
    publisherDID = models.SlugField(blank=True)
    filetype = models.ForeignKey(FileType, blank=True, null=True)
    mime_type = models.CharField(max_length=256, blank=True)
    # size in bytes, KiB?
    size = models.PositiveIntegerField(default=0)
    href = models.URLField(verify_exists=False)
    _container_field = "snapshot_id"
    Snapshot._collection_sets.append('file_set')   

class Array(MetadataObject):
    _collection_sets = []
    file = models.ForeignKey(File)
    property = models.ForeignKey(Property, blank=True, null=True)
    rank = models.PositiveIntegerField(default=1, blank=True)
    offset = models.PositiveIntegerField(default=0, blank=True)
    stride = models.PositiveIntegerField(default=1, blank=True)
    skipbyte = models.PositiveIntegerField(default=0, blank=True)
    endian = models.CharField(max_length=256, 
                              choices=(('BIG', 'Big endian'),
                                       ('LITTLE', 'Little endian')), blank=True)
    row_major = models.BooleanField(default=True, blank=True)
    internal_path = models.CharField(max_length=1024, blank=True)
    # lazy, support only up to 3 dimensions
    left_edge0 = models.FloatField(default=0.0, blank=True)
    left_edge1 = models.FloatField(default=0.0, blank=True)
    left_edge2 = models.FloatField(default=0.0, blank=True)
    right_edge0 = models.FloatField(default=1.0, blank=True)
    right_edge1 = models.FloatField(default=1.0, blank=True)
    right_edge2 = models.FloatField(default=1.0, blank=True)
    _container_field = "file_id"
    File._collection_sets.append('array_set')

class TargetObjectType(ObjectType):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    identityname = models.CharField(max_length=1024, blank=True)
    label = models.CharField(max_length=1024, blank=True)
    _container_field = "experiment_id"
    Experiment._collection_sets.append('targetobjecttype_set')

class TargetProcess(ObjectType):
    _collection_sets = []
    experiment = models.ForeignKey(Experiment)
    astrojournalsubject = models.CharField(max_length=1024, blank=True)
    _container_field = "experiment_id"
    Experiment._collection_sets.append('targetprocess_set')

class ObjectCollection(MetadataObject):
    _collection_sets = []
    snapshot = models.ForeignKey(Snapshot)
    objecttype = models.ForeignKey(ObjectType)   
    numberofobjects = models.PositiveIntegerField(default=1, blank=True, null=True)
    properties = models.ManyToManyField(Property,
                                        related_name="objectcollection_property_set")
    _container_field = "snapshot_id"
    Snapshot._collection_sets.append('objectcollection_set')

class Characterisation(MetadataObject):
    _collection_sets = []
    objectcollection = models.ForeignKey(ObjectCollection)
    axis = models.ForeignKey(Property, blank=True, null=True)
    value_value = models.CharField(max_length=1024, blank=True)
    value_unit = models.CharField(max_length=1024, blank=True)
    characterisation_type = models.CharField(max_length=256, 
                                             choices=CHARACTERISATION_TYPES,
                                             default='nominal')
    apriori = models.BooleanField(default=False)
    _container_field = "objectcollection_id"
    ObjectCollection._collection_sets.append('characterisation_set')

